/**
 * 自定义圆形弧线布局
 * @author houjinhui
 */
import G6 from '@antv/g6'
import { CIRCULAR_ARC } from '@/components/graph-analysis/right-drawer/style-layout-config/style-layout'

interface KeyValue {
  [key: string]: any
}

/**
 *
 * @param a
 * @param b
 */
function compareDegree(a: any, b: any) {
  const aDegree = a.degree
  const bDegree = b.degree
  if (aDegree < bDegree) {
    return -1
  }
  if (aDegree > bDegree) {
    return 1
  }
  return 0
}

/**
 * 自定义画布布局
 */
export default function registerCircularArcG6Layout() {
  // 环形弧线布局
  G6.registerLayout(CIRCULAR_ARC, {
    // 定义自定义行为的默认参数，会与用户传入的参数进行合并,这里的参数和 style-layout.ts 里的参数保持一致
    getDefaultCfg() {
      return {
        isAutoRadius: true, // 自适应圆半径
        radius: null, // 指定圆半径
        ordering: 'degree',
      }
    },
    /**
     * 初始化
     * @param {Object} data 数据
     */
    init(data: any) {
      const self = this // this 指向当前布局
      self.nodes = data.nodes
      self.edges = data.edges
    },
    /**
     * 执行布局
     */
    execute() {
      const self: any = this
      const { edges, nodes, width, height, isAutoRadius, ordering } = self
      const nodesLength = nodes.length
      const angleSeparator = (Math.PI * 2) / nodesLength
      if (!self.width && typeof window !== 'undefined') {
        self.width = window.innerWidth
      }
      if (!self.height && typeof window !== 'undefined') {
        self.height = window.innerHeight
      }
      // 允许指定指定中心的情况
      // if (!self.center) {
      //   self.center = [self.width / 2, self.height / 2]
      // }
      const nodeMap: any = {}
      nodes.forEach((node: any, index: number) => {
        nodeMap[node.id] = index
      })
      self.nodeMap = nodeMap
      self.degrees = G6.Util.getDegree(nodes.length, nodeMap, edges)
      let layoutNodes = [] // 排序好的节点
      if (ordering === 'topology') {
        layoutNodes = self.topologyOrdering()
      } else if (ordering === 'topology-directed') {
        layoutNodes = self.topologyOrdering(true)
      } else if (ordering === 'degree') {
        layoutNodes = self.degreeOrdering()
      } else {
        layoutNodes = nodes
      }
      // 圆的半径 radius
      let { radius } = self
      if (!isAutoRadius && !radius) {
        radius = self.height > self.width ? self.width / 1.8 : self.height / 1.8
      } else if (isAutoRadius) {
        // 自定义自适应画布
        radius = self.height > self.width ? self.width / 2.8 : self.height / 2.8
      }
      const origin = [width / 2, height / 2]
      layoutNodes.forEach((node: any, index: number) => {
        const angle = index * angleSeparator
        node.x = radius * Math.cos(angle) + origin[0]
        node.y = radius * Math.sin(angle) + origin[1]
      })
      edges.forEach((edge: any) => {
        edge.type = 'quadratic'
        edge.style.lineWidth = edge.weight ? edge.weight : 1
        edge.controlPoints = [{ x: origin[0], y: origin[1] }]
      })
      return {
        nodes: layoutNodes,
        edges,
      }
    },
    /**
     * 根据节点度数大小排序
     * @return {array} orderedNodes 排序后的结果
     */
    degreeOrdering() {
      const self: any = this
      const { nodes, degrees } = self
      const orderedNodes: any[] = []
      nodes.forEach((node: any, index: number) => {
        node.degree = degrees[index]
        orderedNodes.push(node)
      })
      orderedNodes.sort(compareDegree)
      return orderedNodes
    },
    /**
     * 根据传入的数据进行布局
     * @param {Object} data 数据
     */
    layout(data: any) {
      const self = this
      self.init(data)
      self.execute()
    },
    /**
     * 更新布局配置，但不执行布局
     * @param {Object} cfg 需要更新的配置项
     */
    updateCfg(cfg: any) {
      const self = this
      G6.Util.mix(self, cfg)
    },
    /**
     * 销毁
     */
    destroy() {
      const self = this
      self.positions = null
      self.nodes = null
      self.edges = null
      self.destroyed = true
    },
  })
}
